CVE-2020-1938(Tomcat AJP)漏洞分析

基础知识

Apache Tomcat服务器通过Connector连接器组件与客户程序建立连接,Connector表示接收请求并返回响应的端点。即Connector组件负责接收客户的请求,以及把Tomcat服务器的响应结果发送给客户。在Apache Tomcat服务器中我们平时用的最多的8080端口,就是所谓的Http Connector,使用Http(HTTP/1.1)协议

在conf/server.xml文件里,他对应的配置为

1
<Connector port="8080" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443" />

而 AJP Connector,它使用的是 AJP 协议(Apache Jserv Protocol)是定向包协议。因为性能原因,使用二进制格式来传输可读性文本,它能降低 HTTP 请求的处理成本,因此主要在需要集群、反向代理的场景被使用。Ajp协议对应的配置为

1
<Connector port="8009" protocol="AJP/1.3" redirectPort="8443" />

漏洞跟进

Tomcat默认启动会启动8009端口,即AJP协议对应端口,其处理逻辑在AjpProcessorservice函数中
0.png
跟进到其中的prepareRequest函数
1.png
当执行到请求头解析阶段时,会判断attributeCode,假设attributeCode等于10,则进入到下图所示的case当中,当请求头的key不满足前三个选项时,直接讲对应的key/value写入到请求的Attribute
2.png
紧接着回到AjpProcessorservice函数中,走到getAdapter().service()处,该函数往后的逻辑属于正常请求分发
3.png
4.png
当走到ApplicationFilterChain时,存在以下判断,假设请求不是http请求,则使用默认servlet进行处理
5.png
默认的DefaultServlet用于处理静态资源,其核心逻辑在serveResource函数中
6.png
7.png
跟进getRelativePath函数
8.png
发现从请求的INCLUDE_PATH_INFOINCLUDE_SERVLET_PATH中获取路径信息并进行拼接并返回,将得到的路径获取对应的resource,最终读取文件
9.png

路径过滤在getResource的过程中,会调用org.apache.tomcat.util.http.RequestUtil.normalize函数进行路径过滤
10.png
不难发现,没有办法使用诸如...进行路径穿越,也没办法使用绝对路径,因此只能读取tomcat的ROOT应用目录